using System;
using System.Web.UI;
using System.Net;
using System.IO;
using System.Web;
using SoftwareMonkeys.Scriptech.Diagnostics;
using System.ComponentModel;

namespace SoftwareMonkeys.Scriptech.Scripts
{
	public class Console
	{
		public ConsoleWriter ContainerWriter;
		
		public Console (ConsoleWriter writer)
		{
			using (LogGroup logGroup = LogGroup.StartDebug("Constructing console."))
			{
				ContainerWriter = writer;
			}
		}
		
		public void Write(string output)
		{
			using (LogGroup logGroup = LogGroup.StartDebug("Writing console output."))
			{
				LogWriter.Debug("Output: " + output);
				
				ContainerWriter.Write(output);
			}
		}
		
		public void WriteLine(string output)
		{
			using (LogGroup logGroup = LogGroup.StartDebug("Writing console output line."))
			{
				LogWriter.Debug("Output: " + output);
				
				bool isRaw = HttpContext.Current.Request.QueryString["Raw"] != null && HttpContext.Current.Request.QueryString["Raw"].ToLower() == "true";
				
				if (!isRaw)
					ContainerWriter.Write("<p>");
				
				ContainerWriter.Write(output);
				
				if (!isRaw)
					ContainerWriter.Write("</p>");
				
				Flush();
			}
		}
		
		public void WriteHeading(string heading)
		{
			Write("<h1>" + heading + "</h1>");
			WriteNewLine();
		}
		
		public void WriteSubHeading(string heading)
		{
			Write("<h2>" + heading + "</h2>");
			WriteNewLine();
		}
		
		public void WriteTrail(params string[] items)
		{
			WriteRule();
			
			WriteLineStart();
			
			for (int i = 0; i < items.Length; i++)
			{
				string part1 = items[i].Substring(0, items[i].IndexOf('='));
				string part2 = items[i].Substring(items[i].IndexOf('=')+1, items[i].Length-items[i].IndexOf('=')-1);
				
				if (part1 == String.Empty || part2 == String.Empty)
					throw new ArgumentException("Invalid trail argument '" + items[i] + "'. Must be [Text]=[Link].");
				
				WriteScriptLink(part1, part2);
				
				if (i < items.Length-1)
					Write(" - ");
			}
			
			WriteLineEnd();
			
			WriteRule();
		}
		
		#region Link functions
		
		public void WriteLink(string text, string url)
		{
			string link = "<a href='" + ResolveLink(url) + "'>" + text + "</a>";
			
			Write(link);
		}
		
		public void WriteLink(string text, string url, string target)
		{
			string link = "<a href='" + ResolveLink(url) + "' target='" + target + "'>" + text + "</a>";
			
			Write(link);
		}
		
		public void WriteLinkLine(string text, string url)
		{
			WriteLineStart();
			
			WriteLink(text, url);
			
			WriteLineEnd();
		}
		
		public void WriteLinkLine(string text, string url, string target)
		{
			WriteLineStart();
			
			WriteLink(text, url, target);
			
			WriteLineEnd();
		}
		
		public void WriteNewLine()
		{
			Write("\r\n");
			Flush();
		}
		
		#endregion
		
		#region Script link functions
		
		public void WriteScriptLink(string text, string script, string queryStrings)
		{
			if (queryStrings != String.Empty)
				queryStrings = "?" + queryStrings;
			
			WriteLink(text, "/Scripts/" + script + queryStrings);
		}
		
		public void WriteScriptLink(string text, string script, string queryStrings, string target)
		{
			if (queryStrings != String.Empty)
				queryStrings = "?" + queryStrings;
			
			WriteLink(text, "/Scripts/" + script + queryStrings, target);
		}
		
		
		public void WriteScriptLinkLine(string text, string script)
		{
			WriteLineStart();
			
			WriteScriptLink(text, script, String.Empty);
			
			WriteLineEnd();
		}
		
		public void WriteScriptLinkLine(string text, string script, string queryStrings)
		{
			WriteLineStart();
			
			WriteScriptLink(text, script, queryStrings);
			
			WriteLineEnd();
		}
		
		public void WriteScriptLinkLine(string text, string script, string queryStrings, string target)
		{
			WriteLineStart();
			
			WriteScriptLink(text, script, queryStrings, target);
			
			WriteLineEnd();
		}
		
		public void WriteScriptLink(string text, string script)
		{
			WriteScriptLink(text, script, "");
		}
		
		public void WriteRawScriptLink(string text, string script, string queryStrings, string target)
		{
			if (queryStrings != String.Empty)
				queryStrings = "?" + queryStrings;
			
			
			WriteLink(text, ResolveLink("/Scripts/" + script + queryStrings), target);
		}
		
		public void WriteRawScriptLink(string text, string script, string queryStrings)
		{
			if (queryStrings != String.Empty)
				queryStrings = "?" + queryStrings;
			
			WriteLink(text, ResolveLink("/Scripts/" + script + queryStrings));
		}
		
		#endregion
		
		public void WriteRule()
		{
			Write("<hr/>");
		}
		
		
		public void WriteBreak()
		{
			WriteLineStart();
			Write("&nbsp;");
			WriteLineEnd();
		}
		
		public void WriteLineStart()
		{
			Write("<div>");
		}
		
		public void WriteLineEnd()
		{
			Write("</div>");
		}
		
		#region Call script functions
		/// <summary>
		/// Launches the specified script name.
		/// </summary>
		/// <param name="scriptName">
		/// The name of the script to launch.
		/// </param>
		/// 
		public void Call(string scriptName)
		{
			Call(scriptName, String.Empty);
		}
		
		public void Call(string scriptName, string queryString)
		{
			using (LogGroup logGroup = LogGroup.StartDebug("Calling script '" + scriptName  + queryString + "'."))
			{
				Write("<div class='SubScript'>");
				
				string fullScriptName = scriptName + "?" + queryString;
				
				WriteLine("<span class='CallingScriptTitle'>Starting script: " + fullScriptName + "</span> [<a href='" + new UrlMapper().MapUrl("/EditScript.aspx") + "?Script=" + fullScriptName.Replace("?", "&") + "'>Edit</a>]");
				
				if (queryString != String.Empty)
					queryString = "?" + queryString;
				
				if (queryString.ToLower().IndexOf("showtemplate=") == -1)
					queryString = queryString + "&ShowTemplate=false";
				
				string url = new UrlMapper().MapUrl("/Scripts/" + scriptName, queryString);
				
				WebRequest request = HttpWebRequest.Create(url);
				request.Timeout = 600000000;
				
				string content = String.Empty;
				
				try
				{
					content = new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();
					
					HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
					doc.LoadHtml(content);
					
					HtmlAgilityPack.HtmlNode bodyNode = doc.DocumentNode.SelectSingleNode("//body");
					
					if (bodyNode == null)
						throw new Exception("Can't find BODY tag.");
					
					string data = bodyNode.InnerHtml.Trim();
					
					LiteralControl control = new LiteralControl(data);
					
					HtmlTextWriter writer = (HtmlTextWriter)ContainerWriter.InnerWriter;
					
					control.RenderControl(writer);
					
					WriteLine("...done.");
				
					writer.Flush();
				}
				catch (Exception ex)
				{
					LogWriter.Error(ex);
					
					Write(ex.ToString().Replace("\n", "<br/>"));
					
					WriteLine("...failed!");
				}
				
				Write("</div>");
			}
		}
		#endregion
		
		public string ResolveLink(string link)
		{
			return new UrlMapper().MapUrl(link);
		}
		
		public void AssertArgument(string value, string argumentName, string message)
		{
			if (value == null || value == String.Empty)
			{
				throw new ArgumentException(message, argumentName);
			}
		}
		
		public void Flush()
		{
			ContainerWriter.Flush();
		}
	}
	
}

